package com.ec.system.modules.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ec.common.constant.CommonConstant;
import com.ec.core.common.core.base.BasePageVO;
import com.ec.core.common.core.node.NodeManager;
import com.ec.core.common.exception.BizException;
import com.ec.core.common.utils.BeanUtilEx;
import com.ec.core.common.utils.StringUtilsEx;
import com.ec.core.mybatis.entity.BaseEntity;
import com.ec.core.mybatis.entity.TenantEntity;
import com.ec.core.mybatis.utils.CorePageUtil;
import com.ec.core.secure.utils.SecureUtil;
import com.ec.system.common.enums.RespResultEnum;
import com.ec.system.modules.sys.dto.QueryDeptDTO;
import com.ec.system.modules.sys.dto.SysDeptDTO;
import com.ec.system.modules.sys.entity.SysDept;
import com.ec.system.modules.sys.mapper.SysDeptMapper;
import com.ec.system.modules.sys.service.ISysDeptService;
import com.ec.system.modules.sys.vo.DeptTreeVO;
import com.ec.system.modules.sys.vo.SysDeptVO;
import com.google.common.collect.Lists;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: Eric Lee
 * @time: 2021/7/20 17:54
 */
@Service
public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> implements ISysDeptService {

    @Override
    public BasePageVO<SysDeptVO> listDept(QueryDeptDTO listDeptDTO) {
        LambdaQueryWrapper<SysDept> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(TenantEntity::getTenantId, SecureUtil.userTenantId());
        if (StringUtilsEx.isNotBlank(listDeptDTO.getDeptName())) {
            wrapper.like(SysDept::getDeptName, listDeptDTO.getDeptName());
        }
        Page<SysDept> page = page(new Page<>(listDeptDTO.getPageNo(), listDeptDTO.getPageSize()), wrapper);
        return CorePageUtil.buildPageResult(page, SysDeptVO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addDept(SysDeptDTO deptDTO) {
        SysDept sysDept = new SysDept();
        BeanUtilEx.copyProperties(deptDTO, sysDept);
        sysDept.setTenantId(SecureUtil.userTenantId());
        return this.save(sysDept);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateDept(SysDeptDTO deptDTO) {
        LambdaUpdateWrapper<SysDept> updateWrapper = Wrappers.<SysDept>lambdaUpdate()
                .set(SysDept::getDeptName, deptDTO.getDeptName())
                .set(SysDept::getParentId, deptDTO.getParentId())
                .set(SysDept::getDeptSort, deptDTO.getDeptSort())
                .set(SysDept::getDeptDesc, deptDTO.getDeptDesc())
                .eq(SysDept::getDeptId, deptDTO.getDeptId())
                .eq(SysDept::getTenantId, SecureUtil.userTenantId());
        return this.update(new SysDept(), updateWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteDept(SysDeptDTO deptDTO) {
        LambdaQueryWrapper<SysDept> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(SysDept::getParentId, deptDTO.getDeptId());
        if(count(wrapper)>0){
            throw new BizException(RespResultEnum.THERE_ARE_CHILD_NODES_ERROR);
        }
        LambdaUpdateWrapper<SysDept> updateWrapper = Wrappers.<SysDept>lambdaUpdate()
                .eq(SysDept::getDeptId, deptDTO.getDeptId())
                .eq(SysDept::getTenantId, SecureUtil.userTenantId());
        return super.remove(updateWrapper);
    }

    @Override
    public List<DeptTreeVO> allDeptTree(QueryDeptDTO queryDeptDTO) {
        LambdaQueryWrapper<SysDept> query = new LambdaQueryWrapper<>();
        query.select(SysDept::getTenantId, SysDept::getDeptId, SysDept::getDeptName, SysDept::getParentId);
        query.eq(BaseEntity::getIsDelete,0);
        if (SecureUtil.isHeadquarters()) {
            if (!Objects.isNull(queryDeptDTO.getTenantId())) {
                query.eq(SysDept::getTenantId, queryDeptDTO.getTenantId());
            }
        } else {
            query.eq(SysDept::getTenantId, SecureUtil.userTenantId());
        }
        query.orderByAsc(BaseEntity::getCreateTime);
        return buildDeptTree(list(query));
    }

    private List<DeptTreeVO> buildDeptTree(List<SysDept> list) {
        List<DeptTreeVO> treeNodes = list.stream().map(e -> {
            DeptTreeVO node = new DeptTreeVO();
            node.setDeptName(e.getDeptName());
            node.setDeptId(e.getDeptId());
            node.setId(e.getDeptId());
            node.setParentId(e.getParentId());
            return node;
        }).collect(Collectors.toList());
        List<DeptTreeVO> deptTreeVO = NodeManager.buildTreeNode(treeNodes, 0L);
        return deptTreeVO;
    }

    @Override
    public List<DeptTreeVO> tenantDeptTree() {
        QueryWrapper<SysDept> query = Wrappers.query();
        query.select("tenant_id", "dept_id", "dept_name", "parent_id");
        query.eq("tenant_id", SecureUtil.userTenantId());
        query.orderByDesc("dept_sort");
        return buildDeptTree(this.list(query));
    }


    @Override
    public List<SysDept> findTenantDeptNodes(Long deptId, Long tenantId) {
        return baseMapper.findTenantDeptNodes(deptId, tenantId);
    }
}
